class Snake {
    // 表示蛇头的元素
    head: HTMLElement
    // 表示蛇的身体
    bodies: HTMLCollection

    // 获取蛇的容器
    element: HTMLElement

    constructor() {
        this.element = document.getElementById('snake')!
        this.head = document.querySelector('#snake>div')!// 找到蛇头
        this.bodies = this.element.getElementsByTagName('div')

    }

    // 获取蛇头的X坐标
    get X() {
        return this.head.offsetLeft
    }

    // 获取蛇头的Y轴坐标
    get Y() {
        return this.head.offsetTop
    }

    //设置蛇头的坐标
    set X(value: number) {
        // 如果新旧位置一致，直接返回不再修改
        if (this.X === value) {
            return
        }
        // X的值的合法范围0~290之间
        if (value < 0 || value > 290) {
            // 进入判断说明蛇撞墙了，抛出一个异常，通知控制器结束游戏
            throw new Error('蛇撞墙了，game over!')
        }
        // 修改X时，是修改水平坐标，蛇在左右移动，蛇在向左移动时，不能向右掉头，反之亦然
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
            console.log('水平方向发生了掉头')
            // 发生掉头，让蛇向反方向继续运动
            if (value > this.X) {
                // 如果新值value大于旧值X，则说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
                value = this.X - 10
            } else {
                // 向左走
                value = this.X + 10
            }
        }

        // 移动身体
        this.moveBody()
        this.head.style.left = value + 'px'

        // 检查有没有撞到自己
        this.checkHeadBody()
    }

    set Y(value: number) {
        // 如果新旧位置一致，直接返回不再修改
        if (this.Y === value) {
            return
        }

        // Y的值的合法范围0~290之间
        if (value < 0 || value > 290) {
            // 进入判断说明蛇撞墙了，抛出一个异常，通知控制器结束游戏
            throw new Error('蛇撞墙了，game over!')
        }
        // 修改Y时，是修改垂直坐标，蛇在上下移动，蛇在向上移动时，不能向下掉头，反之亦然
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
            console.log('垂直方向发生了掉头')
            if (value > this.Y) {
                value = this.Y - 10
            } else {
                value = this.Y + 10
            }
        }
        // 移动身体
        this.moveBody()
        this.head.style.top = value + 'px'

        // 检查有没有撞到自己
        this.checkHeadBody()
    }


    // 蛇增加身体的方法

    addBody() {
        // 向element中添加一个div
        this.element.insertAdjacentHTML("beforeend", "<div></div>")
    }

    // 添加一个移动蛇身体的方法
    moveBody() {
        console.log(this.bodies.length)
        /*
        * 第4节=第3节的位置
        * 第3节=第2节的位置
        * 第2节=蛇头的位置
        *以此类推，从后往前依次修改替换
        * */
        // 遍历获取所有的身体
        for (let i = this.bodies.length - 1; i > 0; i--) {
            // 获取前边身体的位置
            let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
            let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

            // 将值设置为当前身体上
            (this.bodies[i] as HTMLElement).style.left = X + 'px';
            (this.bodies[i] as HTMLElement).style.top = Y + 'px';
        }
    }

    checkHeadBody() {
        // 获取所有的身体，检查其是否和蛇头的坐标发生重叠
        for (let i = 1; i < this.bodies.length; i++) {
            let bd = this.bodies[i] as HTMLElement
            if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
                // 进入判断说明蛇头撞到了身体，游戏结束
                throw  new Error('撞到自己了！！game over！')
            }
        }
    }


}

export default Snake